#include "sdk_port.h"
#include "sdk_proto.h"
#include "netinet/in.h"
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include "sdk.h"
#include <string.h>
#include <stdio.h>

#include "sdk_model_light.h"
#include "sdk_model_generic.h"
#include "sdk_model_curtain.h"
#include "sdk_model_CAC.h"

unsigned char debug_on = 0;

#define SDK_VERSION "0.0.2"
char *sdk_version(void)
{
    return SDK_VERSION;
}

void sdk_param_set(const char *cmd)
{
    if(cmd==NULL){
        return;
    }
    if(strcmp(cmd,"debugon")==0){
        debug_on = 1;
    }else if(strcmp(cmd,"debugoff")==0){
        debug_on = 0;
    }
}

int sdk_auth_status(void)
{
    if(strlen(sdk_proto_context_get()->accesskey)==0){
        sdk_printf("%s:unauth status\r\n",__FUNCTION__);
        return SDK_UNAUTH_ERR;
    }
    return SDK_OK;
}

int sdk_init(unsigned char retry,char devid[35],char productKey[15],char deviceSecret[35])
{
    sdk_printf("version[%s]\r\n",SDK_VERSION);
    sdk_proto_context_clear();
    sdk_proto_send_retry_set(retry);
    if(strlen((char *)devid)>34 || strlen((char *)productKey)>14 || strlen((char *)deviceSecret)>34){
        sdk_printf("%s:license settiing error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    sdk_proto_license_load((uint8_t*)devid,(uint8_t*)productKey,(uint8_t*)deviceSecret);
    return SDK_OK;
}

int sdk_buffer_set(unsigned char *authbuf,int authlen,unsigned char *databuf,int datalen)
{
    if(authbuf==NULL || authlen<0){
        sdk_printf("%s:auth buffer setting error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(databuf==NULL || datalen<0){
        sdk_printf("%s:data buffer setting error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    auth_buffer = authbuf;
    auth_buffer_len = authlen;
    data_buffer = databuf;
    data_buffer_len =  datalen;
    return SDK_OK;
}


int sdk_target_ip_set(char ipstr[16],unsigned char len)
{
    if(len!=strlen(ipstr) || len > 15){
        sdk_printf("%s:params error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    uint8_t count = 0;
    char *ptr = ipstr;
    while(ptr = strchr(ptr,'.'),ptr){
        ptr++;
        count++;
    }
    sdk_printf("count=%u\r\n",count);
    if(count!=3){
        sdk_printf("%s: ip address should be like this,xxx.xxx.xxx.xxx\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    sdk_proto_target_set(ipstr);
    sdk_proto_target_set_authport(0);
    sdk_proto_target_set_dataport(0);

    if(0!=sdk_proto_auth_socket_init()){
        sdk_printf("%s:auth socket init error.\r\n",__FUNCTION__);
        return SDK_SOCKINIT_ERR;
    }

    //create auth receive thread
    if(SDK_OK!=sdk_proto_auth_recv_thread_init()){
        sdk_printf("%s:auth thread init error.\r\n",__FUNCTION__);
        return SDK_THREAD_ERR;
    }


    return SDK_OK;
}

int sdk_target_ip_port_set(char ipstr[16],unsigned char len,unsigned short authport,unsigned short dataport)
{
    if(len!=strlen(ipstr) || len > 15){
        sdk_printf("%s:params error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    uint8_t count = 0;
    char *ptr = ipstr;
    while(ptr = strchr(ptr,'.'),ptr){
        ptr++;
        count++;
    }
    sdk_printf("count=%u\r\n",count);
    if(count!=3){
        sdk_printf("%s: ip address should be like this,xxx.xxx.xxx.xxx\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if( (authport>8000) && (authport<9000)){
        sdk_printf("%s: port should be in 8000-8999.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if((dataport>8000) && (dataport<9000)){
        sdk_printf("%s: port should be in 8000-8999.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    sdk_proto_target_set(ipstr);
    sdk_proto_target_set_authport(authport);
    sdk_proto_target_set_dataport(dataport);

    if(0!=sdk_proto_auth_socket_init()){
        sdk_printf("%s:auth socket init error.\r\n",__FUNCTION__);
        return SDK_SOCKINIT_ERR;
    }

    //create auth receive thread
    if(SDK_OK!=sdk_proto_auth_recv_thread_init()){
        sdk_printf("%s:auth thread init error.\r\n",__FUNCTION__);
        return SDK_THREAD_ERR;
    }


    return SDK_OK;


}





int sdk_heart_beat(void (*fp)(int),int code)
{
    return sdk_proto_hello_send(fp,code);
}





int sdk_auth_regist_send(unsigned char retry)
{
    return sdk_proto_auth(retry);
}
int sdk_auth_unregist_send(unsigned char retry)
{
    return sdk_proto_unregist(retry);
}

int sdk_auth_recv(void)
{
    uint8_t data[512]={0};
    return sdk_proto_auth_recv(data,sizeof(data));
}

int sdk_data_recv(void)
{
    uint8_t data[512]={0};
    return sdk_proto_data_recv(data,sizeof(data));
}


int sdk_auth_get_desction_file(char *buffer,int len)
{
    if(buffer==NULL || len < 100){
        sdk_printf("%s:buffer==NULL or len < 100\r\n",__FUNCTION__);
    }
    return sdk_proto_get_descfile(buffer,len);
}


int sdk_light_ctl_cw(unsigned short addr,unsigned char onoff,unsigned char lnss ,unsigned char colortemp)
{
    if(addr==0){
        sdk_printf("%s:addr=0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(onoff == 0x00){
        onoff = 0x00;
    }else{
        onoff = 0x01;
    }


    if(colortemp>100){
        sdk_printf("%s:colortemp[0-100]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }


    O_LIGHT_DATA data;
    memset(&data,0,sizeof(data));
    data.cw.addr = addr;
    data.cw.onoff = onoff;
    data.cw.colortemp = colortemp;
    data.cw.lnss = lnss;
    return sdk_model_light_ctl(enum_light_ctl_cw,&data);  
}



int sdk_light_ctl_color(unsigned short  addr,unsigned char onoff,unsigned short  h,unsigned char s,unsigned char b )
{
    if(addr==0){
        sdk_printf("%s:addr=0\r\n",__FUNCTION__);
        return -1;
    }

    if(onoff == 0x00){
        onoff = 0x00;
    }else{
        onoff = 0x01;
    }

    if(h>360){
        sdk_printf("%s:hue should be in 0-360.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(s>100){
        sdk_printf("%s:saturation should be in 0-100.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(b>100){
        sdk_printf("%s:brightness should be in 0-100.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }



    O_LIGHT_DATA data;
    memset(&data,0,sizeof(data));
    data.color.addr = addr;
    data.color.onoff = onoff;
    data.color.h = h;
    data.color.s = s;
    data.color.b = b;
    return sdk_model_light_ctl(enum_light_ctl_color,&data);  
}


int sdk_light_ctl_sence(unsigned short  addr,unsigned char onoff,unsigned short  senceid)
{
    if(addr==0){
        sdk_printf("%s:addr=0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(onoff){
        onoff =1;
    }

    O_LIGHT_DATA data;
    memset(&data,0,sizeof(data));
    data.sence.addr = addr;
    data.sence.senceid = senceid;
    data.sence.onoff = onoff;
    return sdk_model_light_ctl(enum_light_ctl_sence,&data);  
}



int sdk_light_ctl_multisw(unsigned short  addr,unsigned char bitStatus)
{
    if(addr==0){
        sdk_printf("%s:addr=0\r\n",__FUNCTION__);
        return -1;
    }


    O_LIGHT_DATA data;
    memset(&data,0,sizeof(data));
    data.multisw.addr = addr;
    data.multisw.bitStatus = bitStatus;
    return sdk_model_light_ctl(enum_light_ctl_mutil_sw,&data);  
}


int sdk_light_ctl_rgb_mode(unsigned short  addr,unsigned char speed,unsigned char rgbmode)
{
    if(addr==0){
        sdk_printf("%s:addr=0\r\n",__FUNCTION__);
        return -1;
    }
    if(speed > 100){
        sdk_printf("%s:speed=100\r\n",__FUNCTION__);
        speed = 100;
    }
    if(rgbmode==0){
        sdk_printf("%s:rgmode==0,error\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    O_LIGHT_DATA data;
    memset(&data,0,sizeof(data));
    data.rgbmode.addr = addr;
    data.rgbmode.speed = speed;
    data.rgbmode.mode = rgbmode;
    return sdk_model_light_ctl(enum_light_ctl_rgb_mode,&data);  
}





/*
int sdk_light_ctl_rythem_cw(unsigned short  addr,unsigned char onoff,unsigned char cold,unsigned char warm,unsigned char lnss )
{
    return 0;
}
int sdk_light_ctl_rythem_color(unsigned short  addr,unsigned char onoff,unsigned char h,unsigned char s,unsigned char b )
{
    return 0;
}
*/


int sdk_ctl_sense(unsigned short  addr,unsigned short  senceid)
{
    return sdk_model_genneric_sence(addr,senceid);
}

//ok
int sdk_ctl_onoff(unsigned short addr,unsigned char onoff,unsigned char swidx)
{
    return sdk_model_generic_onoff(addr,onoff,swidx);
}


//ok
int sdk_cloud_report(unsigned short addr,char *msg,unsigned short msglen)
{
    if(addr==0 || msg==NULL || msglen==0 || msglen!=strlen(msg)){
        sdk_printf("%s:params error.\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    return sdk_proto_cloud_report(addr,(uint8_t*)msg,msglen);
}



int sdk_curtain_motor_status_set(unsigned short addr,unsigned char open_close_stop)
{
    if(open_close_stop>3){
        sdk_printf("%s:open_close_stop in [1:open 2:close 3:stop]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.motorstatus = open_close_stop;
    return sdk_model_curtain_ctl(enum_curtain_ctl_motor,addr,&data);
}



int sdk_curtain_motor_percentage_abs_set(unsigned short addr,unsigned char percentage)
{
    if(percentage>100){
        sdk_printf("%s:percentage in [0-100]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    O_CURTAIN_CTL_DATA data;
    data.motorposition_percentage_abs = percentage;
    return sdk_model_curtain_ctl(enum_curtain_ctl_motor_position_abs,addr,&data);
}


int sdk_curtain_direction_set(unsigned short addr,unsigned char direction)
{
    if(direction>1){
        sdk_printf("%s:direction in [0:positive 1:negitive]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.direction = direction;
    return sdk_model_curtain_ctl(enum_curtain_set_direction,addr,&data);
}


int sdk_curtain_hand_drag(unsigned short addr,unsigned char dragFlag)
{
    if(dragFlag>1){
        sdk_printf("%s:dragFlag in [0:no hand drag 1:hand drag]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.handdrag_direction = dragFlag;
    return sdk_model_curtain_ctl(enum_curtain_set_handdrag,addr,&data);
}


int sdk_curtain_motor_percentage_rel_set(unsigned short addr,unsigned char incOrdec,unsigned char percentage)
{
    if(incOrdec>1){
        sdk_printf("%s:incOrdec in [0:decrease 1:increase]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(percentage>100){
        sdk_printf("%s:percentage in [0-100]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.motorposition_precentage_rel.incOrdec = incOrdec;
    data.motorposition_precentage_rel.percentage = percentage;
    return sdk_model_curtain_ctl(enum_curtain_ctl_motor_position_rel,addr,&data);
}

int sdk_curtain_dimming_limit_set(unsigned short addr,unsigned char param)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.dimming_limit = param;
    return sdk_model_curtain_ctl(enum_curtain_set_dimming_limit,addr,&data);
}

int sdk_curtain_angle_control_percentage_set(unsigned short addr,unsigned char percentage)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(percentage>100){
        sdk_printf("%s:percentage in [0-100]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.angel_precentage = percentage;
    return sdk_model_curtain_ctl(enum_curtain_ctl_angle_percentage,addr,&data);
}

int sdk_curtain_angle_control_direction_set(unsigned short addr,unsigned char direction)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(direction>2){
        sdk_printf("%s:direction in [0:trun right 1:stop 2: turn left]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    O_CURTAIN_CTL_DATA data;
    data.angel_direction = direction;
    return sdk_model_curtain_ctl(enum_curtain_ctl_angle_direction,addr,&data);
}


int sdk_aircond_onoff(unsigned short addr,unsigned short subaddr,unsigned char onoff)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    if(onoff!=0){
        onoff = 1;
    }

    O_CAC_DATA data;
    data.onoff = onoff;
    return sdk_model_CAC_ctl(enum_CAC_ctl_onoff,addr,subaddr,&data);
}



int sdk_aircond_temp(unsigned short addr,unsigned short subaddr,unsigned char temp)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(temp<16 || temp>30){
        sdk_printf("%s:temp[16-30]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }


    O_CAC_DATA data;
    data.temp = temp;
    return sdk_model_CAC_ctl(enum_CAC_ctl_temp,addr,subaddr,&data);
}


int sdk_aircond_mode(unsigned short addr,unsigned short subaddr,unsigned char mode)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(mode>10){
        sdk_printf("%s:temp[0-10]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    O_CAC_DATA data;
    data.mode = mode;
    return sdk_model_CAC_ctl(enum_CAC_ctl_mode,addr,subaddr,&data);
}






int sdk_aircond_windspeed(unsigned short addr,unsigned short subaddr,unsigned char speed)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(speed>5){
        sdk_printf("%s:speed[0-5]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    O_CAC_DATA data;
    data.windspeed = speed;
    return sdk_model_CAC_ctl(enum_CAC_ctl_windspeed,addr,subaddr,&data);
}

int sdk_aircond_antifreeze(unsigned short addr,unsigned short subaddr,unsigned char onoff)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(onoff!=0){
        onoff = 1;
    }

    O_CAC_DATA data;
    data.antiFreeze = onoff;
    return sdk_model_CAC_ctl(enum_CAC_ctl_antifreeze,addr,subaddr,&data);
}


int sdk_aircond_wind_direction(unsigned short addr,unsigned short subaddr,unsigned char direction)
{
    if(addr==0){
        sdk_printf("%s:addr==0\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    if(direction!=0 || direction!=1 || direction!=2 || direction!=4 || direction!=7  ){
        sdk_printf("%s:direction[0,1,2,4,7,]\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    O_CAC_DATA data;
    data.winddirection = direction;
    return sdk_model_CAC_ctl(enum_CAC_ctl_winddirection,subaddr,addr,&data);
}



int sdk_device_onoffline_funcb_regist(void (* pfunc)(unsigned short addr,unsigned char onoffline))
{
    if(pfunc==NULL){
        sdk_printf("%s:pfunc==NULL\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }

    sdk_proto_device_onoffline_funcb_regist(pfunc);
    return SDK_OK;
}
int sdk_device_extdata_funcb_regist(int (* pfunc)(unsigned short addr,const char *extdata,unsigned short extdataLen))
{
    if(pfunc==NULL){
        sdk_printf("%s:pfunc==NULL\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    sdk_proto_device_extdata_funcb_regist(pfunc);
    return SDK_OK;
}

int sdk_device_data_funcb_regist(void (* pfunc)(unsigned short addr,const int dtype,void * pdata))
{
    if(pfunc==NULL){
        sdk_printf("%s:pfunc==NULL\r\n",__FUNCTION__);
        return SDK_PARAMS_ERR;
    }
    sdk_proto_device_data_funcb_regist(pfunc);
    return SDK_OK;
}


